{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6191d6b3",
   "metadata": {},
   "source": [
    "# 函数\n",
    "## 1.函数的定义\n",
    "* 1.数学 ：     f(x) = ax + b\n",
    "* 2.python ：def fib(x):\n",
    "* 3.编程思维 vs 数学思维\n",
    "> 1.函数可以被定义名称，定义的关键字：**def**   \n",
    "> 2.数学思维是写在同一行（定义函数和函数体），面向对象编程中，函数写多行，定义函数单独为一行  \n",
    "> 3.数学函数一般没有注释，而编程过程中，一般需要对函数进行注释描述（p151，官方4.7-4.8） \n",
    "> 4.数学中：ax + b 是计算公式，而编程中，我们将函数的内容成为**函数体**，函数体要有一定的**缩进**\n",
    "> 5.数学函数执行，将参数代入公式，编程中函数执行，将参数带入函数体\n",
    "\n",
    "## 2.关于更多函数的定义\n",
    "\n",
    "* 1.函数的参数\n",
    "> 1.形式参数  \n",
    "> 2.实际参数  \n",
    "> 3.默认参数  \n",
    "> 4.位置参数  \n",
    "> 5.关键字参数  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ee7cac2a",
   "metadata": {},
   "source": [
    "### 1.函数的定义"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d30dde06",
   "metadata": {},
   "source": [
    "* 1.定义函数  \n",
    "> def:定义函数的关键字   \n",
    "> flb：函数名   \n",
    "> (n)：定义函数的参数   \n",
    "> \"\"\"\"\"\"：文档描述，与使用者进行交互的唯一途径  \n",
    "> 代码块：   \n",
    ">      a, b = 0, 1  \n",
    ">      while a < n:  \n",
    ">         print(a, end=' ')   \n",
    ">          a, b = b, a+b   \n",
    ">      print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "f87dcf6d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def hello(name):\n",
    "    \"\"\"显示问候语\"\"\"\n",
    "    print(\"你好，%s同学\" %(name))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e903429",
   "metadata": {},
   "source": [
    "* 2.调用函数  \n",
    "> 1.函数名（参数）   \n",
    "> 2.参数可以不存在"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "570c6f38",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好，xiaoma同学\n"
     ]
    }
   ],
   "source": [
    "hello(\"xiaoma\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d079079c",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid character in identifier (<ipython-input-10-4c87aee61182>, line 3)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-10-4c87aee61182>\"\u001b[1;36m, line \u001b[1;32m3\u001b[0m\n\u001b[1;33m    print(\"hello world\"）\u001b[0m\n\u001b[1;37m                       ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid character in identifier\n"
     ]
    }
   ],
   "source": [
    "def hello():\n",
    "    \"\"\"显示问候语\"\"\"\n",
    "    print(\"hello world\"）\n",
    "hello()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69e8f324",
   "metadata": {},
   "source": [
    "* 3.函数的优势  \n",
    "> 1.可以重复使用相同的功能，避免重复造轮子  \n",
    "> 2.使用者可以不了解函数本身，只需清楚如何使用即可  \n",
    "> 3.使用/调用方便，"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "309f9ffc",
   "metadata": {},
   "source": [
    "## 3.函数的参数\n",
    "* 1.形式参数\n",
    "> 1.在**定义**函数的时候定义的参数   \n",
    "> 2.形式参数不占用内存\n",
    "* 2.实际参数\n",
    "> 1.在**调用**函数的时候传递的参数  \n",
    "> 2.调用函数时，形式参数分配空间，传递实际参数，执行函数内容"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "399a8eb3",
   "metadata": {},
   "source": [
    "* 课本函数实践案例\n",
    "> 1.形式参数：word   \n",
    "> 2.实际参数：\"fdsfssfdjhsijkan\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "79128feb",
   "metadata": {},
   "outputs": [],
   "source": [
    "def search4vowels(word):\n",
    "    \"\"\"显示文本中出现的元音字母有哪些\"\"\"\n",
    "    vowels = set(\"aeiou\")\n",
    "    word = set(word)\n",
    "    print(vowels & word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "ea1d0cdc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'i', 'a'}\n"
     ]
    }
   ],
   "source": [
    "search4vowels(\"fdsfssfdjhsijkan\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1e1ec67",
   "metadata": {},
   "source": [
    "* 在多个参数的情景下：\n",
    "* 1.位置参数\n",
    "> 1.在形式参数的定义中，有一定的先后顺序  \n",
    "> 2.在调用函数时，要考虑形式参数的先后顺序  \n",
    "> 3.调用函数时，不仅要考虑参数的位置，还需要考虑形式参数的个数  \n",
    "* 2.关键字参数\n",
    "> 1.在调用函数时，关键字参数可以不考虑形式参数的位置\n",
    "* 3.默认参数\n",
    "> 1.调用函数时，可以省略传递的参数信息\n",
    "> 2.调用函数时，如果给默认参数赋值，会替换默认参数的结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "71609505",
   "metadata": {},
   "outputs": [],
   "source": [
    "def describe_pet(animal_type,pet_name):\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My \" + animal_type + \"'s name is \"+pet_name.title() + \".\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "ee71c0d7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is Doudou.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"dog\",\"doudou\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "d4b02204",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is Doudou.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(animal_type = \"dog\",pet_name = \"doudou\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9fd55bfd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "9843fc48",
   "metadata": {},
   "source": [
    "-----------------\n",
    "* 参数注意事项实践\n",
    "* 位置参数和关键字参数同时使用（调用参数）\n",
    "> 1.位置参数和关键字参数同时使用：positional argument follows keyword argument（关键字参数<font style=\"color:red\">均</font>应该放在位置参数之后）  \n",
    "> 2.只要满足1的条件，剩余的关键字参数（多个）不考虑先后顺序\n",
    "* 2.非默认参数和默认参数同时使用（定义参数）\n",
    "> 1.non-default argument follows default argument（默认参数<font style=\"color:red\">均</font>应该放在非默认参数之后）   \n",
    "> 2.只要满足条件1，剩余的默认参数（多个）不考虑先后顺序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "4be58792",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试1\n",
    "def test(x,y,z):\n",
    "    \"\"\"打印x,y,z结果\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "65a3a931",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "positional argument follows keyword argument (<ipython-input-30-d66e645e9975>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-30-d66e645e9975>\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m    test(5,y=3,2)\u001b[0m\n\u001b[1;37m               ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m positional argument follows keyword argument\n"
     ]
    }
   ],
   "source": [
    "# 实践1( positional argument follows keyword argument)\n",
    "# 关键字参数均应该放在位置参数之后\n",
    "test(5,y=3,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "dd05c0d9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "3\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "# 实践2\n",
    "test(5,3,z=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "d2044165",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "3\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "# 实践3\n",
    "test(5,y=3,z=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f6044764",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "non-default argument follows default argument (<ipython-input-1-0de206ab27d0>, line 2)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-1-0de206ab27d0>\"\u001b[1;36m, line \u001b[1;32m2\u001b[0m\n\u001b[1;33m    def test(x,y=1,z):\u001b[0m\n\u001b[1;37m             ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m non-default argument follows default argument\n"
     ]
    }
   ],
   "source": [
    "# 测试2(non-default argument follows default argument)\n",
    "# 默认参数均应该放在非默认参数之后\n",
    "def test(x,y=1,z):\n",
    "    \"\"\"打印x,y,z的结果\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5f1b2f77",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实践\n",
    "def test(x,z,y=1):\n",
    "    \"\"\"打印x,y,z的结果\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
